package com.example.mybatisplusdemo.service.impl;

import com.example.mybatisplusdemo.common.JsonResponse;
import com.example.mybatisplusdemo.common.utls.LevelCalculatorUtil;
import com.example.mybatisplusdemo.mapper.*;
import com.example.mybatisplusdemo.model.domain.*;
import com.example.mybatisplusdemo.model.dto.CartItemDTO;
import com.example.mybatisplusdemo.model.dto.OrderDTO;
import com.example.mybatisplusdemo.model.dto.OrderProductQuantityDTO;
import com.example.mybatisplusdemo.model.dto.UpdateLevelRequestDTO;
import com.example.mybatisplusdemo.service.IOrderMainService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单详情 服务实现类
 * </p>
 *
 * @author lqj
 * @since 2025-07-02
 */
@Service
public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain> implements IOrderMainService {
    @Autowired
    private OrderMainMapper orderMainMapper;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private PointsHistoryMapper pointsHistoryMapper;
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private ProductMapper productMapper;

    @Transactional
    @Override
    public JsonResponse submitOrder(OrderSubmitRequest request) {
        Long userId = request.getUserId();
        List<CartItemDTO> cartItems = request.getCartItems();
        User user = userMapper.selectById(userId);

        BigDecimal totalAmount = BigDecimal.ZERO;
        int totalPoints = 0;

        for (CartItemDTO item : cartItems) {
            if (item.getPointsMall()) {
                totalPoints += item.getPointsPrice() * item.getQuantity();
            } else {
                totalAmount = totalAmount.add(item.getFinalPrice().multiply(new BigDecimal(item.getQuantity())));
            }
        }

        if (user.getBalance().compareTo(totalAmount) < 0) {
            return JsonResponse.failure("余额不足，差 " + totalAmount.subtract(user.getBalance()) + " 元");
        }

        if (user.getPoints() < totalPoints) {
            return JsonResponse.failure("积分不足，差 " + (totalPoints - user.getPoints()) + " 分");
        }

        // 1. 插入 order_main 表
        OrderMain orderMain = new OrderMain();
        orderMain.setUserId(userId);
        orderMain.setOrderNo(UUID.randomUUID().toString().replace("-", "").substring(0, 16));
        orderMain.setStatus(1); // 待发货
        orderMain.setTotalAmount(totalAmount);
        orderMain.setPaymentAmount(totalAmount);
        orderMain.setAddressId(request.getAddressId());
        orderMain.setCreateTime(LocalDateTime.now());
        orderMain.setUpdateTime(LocalDateTime.now());
        orderMainMapper.insert(orderMain);

        // 2. 插入 order_item 表
        for (CartItemDTO item : cartItems) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(orderMain.getId());
            orderItem.setProductId(item.getProductId());
            orderItem.setQuantity(item.getQuantity());
            orderItem.setPrice(item.getFinalPrice());
            orderItem.setCreateTime(LocalDateTime.now());
            orderItem.setUpdateTime(LocalDateTime.now());
            orderItemMapper.insert(orderItem);
        }

        // 3. 更新 user 表：余额、积分、消费
        user.setBalance(user.getBalance().subtract(totalAmount));
        user.setPoints(user.getPoints() - totalPoints);
        user.setTotalConsumption(user.getTotalConsumption().add(totalAmount));
        user.setUpdateTime(LocalDateTime.now());
        userMapper.updateById(user);

        // 4. 插入 points_history 表
        if (totalPoints > 0) {
            PointsHistory history = new PointsHistory();
            history.setUserId(userId);
            history.setPoints(-totalPoints);
            history.setChangeType(2); // 2 = 订单消费
            history.setSourceId(orderMain.getId());
            history.setCreateTime(LocalDateTime.now());
            history.setUpdateTime(LocalDateTime.now());
            pointsHistoryMapper.insert(history);
        }

        // 👉 计算返还积分
        int totalReturnedPoints = 0;
        for (CartItemDTO item : cartItems) {
            if (!item.getPointsMall()) {
                BigDecimal returned = item.getFinalPrice()
                        .multiply(BigDecimal.valueOf(0.1))
                        .multiply(user.getPointsMultiplier())
                        .multiply(BigDecimal.valueOf(item.getQuantity()));
                totalReturnedPoints += returned.intValue();
            }
        }

// 👉 更新用户积分
        user.setPoints(user.getPoints() + totalReturnedPoints);
        userMapper.updateById(user);

// 👉 记录到积分变动历史
        PointsHistory history = new PointsHistory();
        history.setUserId(user.getId());
        history.setPoints(totalReturnedPoints);
        history.setChangeType(1); // 1 = 消费返还
        history.setSourceId(orderMain.getId()); // 订单号或主键
        history.setCreateTime(LocalDateTime.now());

        pointsHistoryMapper.insert(history);

        // 5. 清空购物车中已提交商品（假设你有方法 deleteCartItemsByIds）
        List<Long> cartItemIds = cartItems.stream()
                .map(CartItemDTO::getCartItemId)
                .collect(Collectors.toList());
        cartMapper.deleteBatchIds(cartItemIds);

        return JsonResponse.success("订单提交成功");
    }

    @Override
    public List<OrderMain> getOrdersByUserId(Long userId) {
        return orderMainMapper.selectOrdersByUserId(userId);
    }

    @Transactional(rollbackFor = Exception.class)
    public int cancelOrder(Long orderId) {
        try {
            // 1. 查询订单
            OrderMain order = orderMainMapper.selectById(orderId);
            if (order == null || order.getDeleted()) {
                // 订单不存在或已取消
                return 0;
            }

            Long userId = order.getUserId();
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }

            // 2. 查找该订单相关的积分记录
            List<PointsHistory> logs = pointsHistoryMapper.selectBySourceId(orderId);
            int usedPoints = 0, returnedPoints = 0;
            for (PointsHistory log : logs) {
                if (log.getChangeType() == 2) {
                    usedPoints += log.getPoints();       // 消费扣减过的积分
                }
                if (log.getChangeType() == 1) {
                    returnedPoints += log.getPoints();   // 下单返还过的积分
                }
                // 标记积分记录为删除
                log.setDeleted(true);
                pointsHistoryMapper.updateById(log);
            }

            // 3. 回滚用户积分
            //   回滚使用的积分，并扣除曾经返还的积分
            user.setPoints(user.getPoints() + usedPoints - returnedPoints);
            userMapper.updateById(user);

            // 4. 添加一条退还“消费积分”的记录（正向）
            if (usedPoints > 0) {
                PointsHistory refundLog = new PointsHistory();
                refundLog.setUserId(userId);
                refundLog.setPoints(usedPoints);
                refundLog.setChangeType(1);      // 1 = 增加
                refundLog.setSourceId(orderId);
                refundLog.setDeleted(false);
                refundLog.setCreateTime(LocalDateTime.now());
                refundLog.setUpdateTime(LocalDateTime.now());
                pointsHistoryMapper.insert(refundLog);
            }

            // 5. 回滚历史消费总额
            user.setTotalConsumption(user.getTotalConsumption().subtract(order.getTotalAmount()));
            user.setBalance(user.getBalance().add(order.getTotalAmount()));
            userMapper.updateById(user);

            // 6. 更新订单状态
            order.setDeleted(true);
            order.setStatus(0); // 设置为取消状态
            order.setUpdateTime(LocalDateTime.now());
            return orderMainMapper.updateById(order);
        } catch (Exception e) {
            log.error("取消订单异常, orderId: " + orderId, e); // 修正后的错误日志
            throw e; // 触发事务回滚
        }
    }

    @Override
    public JsonResponse<List<OrderDTO>> getAllOrders() {
        List<OrderDTO> list = orderMainMapper.selectOrderDTOList();
        list.forEach(order -> {
            order.setStatusLabel(formatOrderStatus(order.getStatus()));
        });
        return JsonResponse.success(list);
    }

    @Override
    @Transactional
    public boolean deliverOrder(Long orderId) {
        // 1. 查询订单
        OrderMain order = orderMainMapper.selectById(orderId);
        if (order == null || order.getStatus() != 1) {
            return false;
        }

        // 2. 查询该订单包含的商品及其数量
        List<OrderProductQuantityDTO> productList = orderItemMapper.selectProductQuantitiesByOrderId(orderId);

        // 3. 遍历每个商品，减少库存
        for (OrderProductQuantityDTO item : productList) {
            int updated = productMapper.decreaseInventory(item.getProductId(), item.getQuantity());
            if (updated == 0) {
                throw new RuntimeException("商品ID: " + item.getProductId() + " 库存不足或不存在");
            }
        }

        // 4. 修改订单状态和发货时间
        order.setStatus(2); // 设置为待收货
        order.setShippingTime(LocalDateTime.now());
        orderMainMapper.updateById(order);

        return true;
    }

    @Override
    @Transactional
    public boolean confirmReceive(Long orderId) {
        OrderMain order = orderMainMapper.selectById(orderId);
        if (order == null || order.getStatus() != 2) { // 只允许“待收货”确认收货
            return false;
        }
        order.setStatus(3); // 已完成
        order.setDeliveryTime(LocalDateTime.now());
        return orderMainMapper.updateById(order) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResponse<Boolean> applyRefund(Long orderId) {
        OrderMain order = orderMainMapper.selectById(orderId);
        if (order == null || order.getDeleted() || !(order.getStatus() == 2 || order.getStatus() == 3)) {
            return JsonResponse.failure("订单不存在或状态不支持退款");
        }

        User user = userMapper.selectById(order.getUserId());
        if (user == null) {
            return JsonResponse.failure("用户不存在");
        }

        BigDecimal amount = order.getPaymentAmount();
        Long level = user.getLevelId();

        boolean directRefund = false;
        String message;

        if (level == 5) {
            directRefund = true;
            message = "尊贵的会员，本单已为您直接退单，为您带来的不便我们深感抱歉";
        } else if (level == 4) {
            if (amount.compareTo(new BigDecimal("1000")) < 0) {
                directRefund = true;
                message = "亲爱的会员，本单我们为您急速退单";
            } else {
                message = "已提交申请，请等待管理员处理";
            }
        } else {
            message = "已提交申请，请等待管理员处理";
        }

        if (directRefund) {
            // 1. 回滚积分记录
            List<PointsHistory> logs = pointsHistoryMapper.selectBySourceId(orderId);
            int usedPoints = 0, returnedPoints = 0;
            for (PointsHistory log : logs) {
                if (log.getChangeType() == 2) {
                    usedPoints += log.getPoints();       // 使用过的积分
                }
                if (log.getChangeType() == 1) {
                    returnedPoints += log.getPoints();   // 曾返还过的积分
                }

                log.setDeleted(true); // 标记为已作废
                pointsHistoryMapper.updateById(log);
            }

            // 2. 回滚用户积分
            user.setPoints(user.getPoints() + usedPoints - returnedPoints);

            // 3. 添加一条退还"消费积分"的记录（正向）
            if (usedPoints > 0) {
                PointsHistory refundLog = new PointsHistory();
                refundLog.setUserId(user.getId());
                refundLog.setPoints(usedPoints);
                refundLog.setChangeType(1);  // 1 = 增加
                refundLog.setSourceId(orderId);
                refundLog.setDeleted(false);
                refundLog.setCreateTime(LocalDateTime.now());
                refundLog.setUpdateTime(LocalDateTime.now());
                pointsHistoryMapper.insert(refundLog);
            }

            // 4. 回滚余额（退款金额加回去）
            user.setBalance(user.getBalance().add(amount));

            // 5. 回滚总消费金额
            BigDecimal newConsumption = user.getTotalConsumption().subtract(amount);
            user.setTotalConsumption(newConsumption);

            // 6. 重新计算等级
            UpdateLevelRequestDTO newLevelInfo = LevelCalculatorUtil.getLevelByConsumption(newConsumption);
            user.setLevelId(newLevelInfo.getLevelId());
            user.setDiscountRate(newLevelInfo.getDiscountRate());
            user.setPointsMultiplier(newLevelInfo.getPointsMultiplier());

            // 7. 更新用户信息
            userMapper.updateById(user);

            // 8. 更新订单状态为"已退款"
            order.setStatus(5);
            order.setUpdateTime(LocalDateTime.now());
            orderMainMapper.updateById(order);
        } else {
            // 设置为退款审核中
            order.setStatus(4);
            order.setUpdateTime(LocalDateTime.now());
            orderMainMapper.updateById(order);
        }

        return JsonResponse.success(true, message);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResponse<Boolean> approveRefund(Long orderId) {
        // 1. 查询订单
        OrderMain order = orderMainMapper.selectById(orderId);
        if (order == null || order.getStatus() != 4) {
            return JsonResponse.failure("订单不存在或状态不为退款审核中");
        }

        // 2. 查询用户
        User user = userMapper.selectById(order.getUserId());
        if (user == null) {
            return JsonResponse.failure("用户不存在");
        }

        BigDecimal refundAmount = order.getPaymentAmount();

        // 3. 回滚积分记录
        List<PointsHistory> logs = pointsHistoryMapper.selectBySourceId(orderId);
        int usedPoints = 0, returnedPoints = 0;
        for (PointsHistory log : logs) {
            if (log.getChangeType() == 2) {
                usedPoints += log.getPoints();       // 使用过的积分
            }
            if (log.getChangeType() == 1) {
                returnedPoints += log.getPoints();   // 曾返还过的积分
            }

            log.setDeleted(true); // 标记为已作废
            pointsHistoryMapper.updateById(log);
        }

        // 回滚用户积分
        user.setPoints(user.getPoints() + usedPoints - returnedPoints);

        // 添加一条退还“消费积分”的记录（正向）
        if (usedPoints > 0) {
            PointsHistory refundLog = new PointsHistory();
            refundLog.setUserId(user.getId());
            refundLog.setPoints(usedPoints);
            refundLog.setChangeType(1);  // 1 = 增加
            refundLog.setSourceId(orderId);
            refundLog.setDeleted(false);
            refundLog.setCreateTime(LocalDateTime.now());
            refundLog.setUpdateTime(LocalDateTime.now());
            pointsHistoryMapper.insert(refundLog);
        }

        // 4. 回滚余额（退款金额加回去）
        user.setBalance(user.getBalance().add(refundAmount));

        // 5. 回滚总消费金额
        BigDecimal newConsumption = user.getTotalConsumption().subtract(refundAmount);
        user.setTotalConsumption(newConsumption);

        // 6. 等级重新计算
        UpdateLevelRequestDTO newLevelInfo = LevelCalculatorUtil.getLevelByConsumption(newConsumption);
        user.setLevelId(newLevelInfo.getLevelId());
        user.setDiscountRate(newLevelInfo.getDiscountRate());
        user.setPointsMultiplier(newLevelInfo.getPointsMultiplier());

        // 7. 更新用户信息
        userMapper.updateById(user);

        // 8. 更新订单状态为“已退款”
        order.setStatus(5);
        order.setUpdateTime(LocalDateTime.now());
        orderMainMapper.updateById(order);

        return JsonResponse.success(true);
    }

    @Override
    @Transactional
    public JsonResponse<Boolean> rejectRefund(Long orderId) {
        OrderMain order = orderMainMapper.selectById(orderId);
        if (order == null || order.getStatus() != 4) {
            return JsonResponse.failure("订单不存在或状态不为退款审核中");
        }

        // 订单状态改为退款被拒绝
        order.setStatus(6);
        order.setUpdateTime(LocalDateTime.now());
        orderMainMapper.updateById(order);

        return JsonResponse.success(true);
    }



    private String formatOrderStatus(Integer status) {
        switch (status) {
            case 0: return "已取消";
            case 1: return "待发货";
            case 2: return "待收货";
            case 3: return "已完成";
            case 4: return "退款审核中";
            case 5: return "已退款";
            default: return "未知状态";
        }
    }

}
